import { writeFileSync } from 'fs';

import { transform } from './transform';

// Mock out FS to avoid writing to disk
// We aren't processing the result anyway, so no need for specifying the response
jest.mock('fs');

describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesToDirectory)', () => {
  describe('with the classic runtime', () => {
    const runtime = 'classic';

    describe('without JSX pragma', () => {
      const code = `
        import '@compiled/react';

        const Component = () => (
          <div css={{ fontSize: 12, color: 'blue' }}>
            hello world
          </div>
        );
      `;

      it('adds styles to directory', () => {
        const actual = transform(code, {
          run: 'both',
          runtime,
          extractStylesToDirectory: { source: 'src/', dest: 'dist/' },
        });

        expect(actual).toMatchInlineSnapshot(`
          "/* app.tsx generated by @compiled/babel-plugin v0.0.0 */
          import './app.compiled.css';
          import * as React from 'react';
          import { ax, ix } from '@compiled/react/runtime';
          const Component = () =>
            /*#__PURE__*/ React.createElement(
              'div',
              {
                className: ax(['_1wyb1fwx _syaz13q2']),
              },
              'hello world'
            );
          "
        `);

        expect(writeFileSync).toBeCalledWith(
          expect.stringContaining('app.compiled.css'),
          '._1wyb1fwx{font-size:12px}\n._syaz13q2{color:blue}'
        );
      });

      it('error when source directory is not found', () => {
        expect(() =>
          transform(code, {
            run: 'both',
            runtime,
            extractStylesToDirectory: { source: 'not-existing-src/', dest: 'dist/' },
          })
        ).toThrowWithMessage(
          Error,
          `/base/src/app.tsx: Source directory 'not-existing-src/' was not found relative to source file ('../src/app.tsx')`
        );
      });
    });

    describe('with JSX pragma', () => {
      it('extracts styles into app.compiled.css', () => {
        const codeWithPragma = `
          /** @jsx myJsx */
          import { css, jsx as myJsx } from '@compiled/react';

          const Component = () => (
            <div css={{ fontSize: 12, color: 'blue' }}>
              hello world 2
            </div>
          );

          const Component2 = () => (
            <div css={css({ fontSize: 12, color: 'pink' })}>
              hello world 2
            </div>
          );
        `;

        const actual = transform(codeWithPragma, {
          run: 'both',
          runtime: 'classic',
          extractStylesToDirectory: { source: 'src/', dest: 'dist/' },
        });

        expect(actual).toMatchInlineSnapshot(`
          "/* app.tsx generated by @compiled/babel-plugin v0.0.0 */
          import './app.compiled.css';
          import * as React from 'react';
          import { ax, ix } from '@compiled/react/runtime';
          const Component = () =>
            /*#__PURE__*/ React.createElement(
              'div',
              {
                className: ax(['_1wyb1fwx _syaz13q2']),
              },
              'hello world 2'
            );
          const Component2 = () =>
            /*#__PURE__*/ React.createElement(
              'div',
              {
                className: ax(['_1wyb1fwx _syaz32ev']),
              },
              'hello world 2'
            );
          "
        `);
      });
    });
  });

  describe('with the automatic runtime', () => {
    describe('with JSX pragma', () => {
      it('extracts styles into app.compiled.css', () => {
        const codeWithPragma = `
          /** @jsxImportSource @compiled/react */
          import { css } from '@compiled/react';

          const Component = () => (
            <div css={{ fontSize: 12, color: 'blue' }}>
              hello world 2
            </div>
          );

          const Component2 = () => (
            <div css={css({ fontSize: 12, color: 'pink' })}>
              hello world 2
            </div>
          );
        `;

        const actual = transform(codeWithPragma, {
          run: 'both',
          runtime: 'automatic',
          extractStylesToDirectory: { source: 'src/', dest: 'dist/' },
        });

        expect(actual).toMatchInlineSnapshot(`
          "/* app.tsx generated by @compiled/babel-plugin v0.0.0 */
          import './app.compiled.css';
          import { ax, ix } from '@compiled/react/runtime';
          import { jsxs as _jsxs, jsx as _jsx } from 'react/jsx-runtime';
          const Component = () =>
            /*#__PURE__*/ _jsx('div', {
              className: ax(['_1wyb1fwx _syaz13q2']),
              children: 'hello world 2',
            });
          const Component2 = () =>
            /*#__PURE__*/ _jsx('div', {
              className: ax(['_1wyb1fwx _syaz32ev']),
              children: 'hello world 2',
            });
          "
        `);
      });
    });
  });
});
